Sikre dine Django REST Framework API-er med robust autentisering. Sammenlign Token-autentisering og JWT (JSON Web Token)-implementering, inkludert praktiske kodeeksempler og beste praksis.
Python DRF Autentisering: Token vs. JWT Implementering for Robuste API-er
Å sikre API-ene dine er avgjørende. Når du bygger API-er med Python og Django REST Framework (DRF), har du flere autentiseringsalternativer tilgjengelig. Denne artikkelen dykker ned i to populære metoder: Token-autentisering og JWT (JSON Web Token)-autentisering, og sammenligner deres styrker og svakheter, og gir praktiske implementeringseksempler.
Forståelse av autentisering i API-er
Autentisering er prosessen med å verifisere identiteten til en bruker eller applikasjon som får tilgang til API-en din. Et godt implementert autentiseringssystem sikrer at bare autoriserte enheter kan få tilgang til beskyttede ressurser. I konteksten av RESTful API-er innebærer autentisering typisk å sende legitimasjon (f.eks. brukernavn og passord) med hver forespørsel. Serveren verifiserer deretter denne legitimasjonen, og hvis den er gyldig, gir den tilgang.
Token-autentisering
Token-autentisering er en enkel og grei mekanisme. Når en bruker logger inn, genererer serveren en unik, tilfeldig token og lagrer den i databasen, og knytter den til brukeren. Klienten sender deretter denne token i 'Authorization'-headeren for påfølgende forespørsler. Serveren henter token fra databasen, verifiserer gyldigheten og gir tilgang deretter.
Implementering med DRF
DRF gir innebygd støtte for Token-autentisering. Slik implementerer du det:
- Installer DRF og registrer det i Django-prosjektet ditt:
Først må du sørge for at du har Django REST Framework installert:
pip install djangorestframework
Deretter legger du det til i `INSTALLED_APPS` i `settings.py`:
INSTALLED_APPS = [
...
'rest_framework',
]
- Legg til TokenAuthentication-skjemaet som en standard autentiseringsklasse (valgfritt, men anbefalt):
I `settings.py`-filen din legger du til følgende:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
}
Dette vil gjelde Token-autentisering globalt på tvers av API-en din. `SessionAuthentication` er inkludert for nettleserbasert interaksjon, men du kan fjerne den for en rent API-drevet applikasjon.
- Opprett en Token for hver bruker:
Du kan automatisk opprette tokens for brukere ved opprettelse ved å legge til en signalhandler. Opprett en fil kalt `signals.py` i appen din (f.eks. `users/signals.py`):
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
Deretter importerer du denne `signals.py`-filen i `users/apps.py`-filen din i `ready`-metoden i appkonfigurasjonsklassen din. Eksempel for `users/apps.py`:
from django.apps import AppConfig
class UsersConfig(AppConfig):
default_auto_field = 'django.db.BigAutoField'
name = 'users'
def ready(self):
import users.signals
Nå kan du administrere tokens ved hjelp av kommandolinjen:
python manage.py drf_create_token <username>
- Implementer API-visningene dine:
Her er et enkelt eksempel på en visning som krever Token-autentisering:
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
content = {
'message': 'Hallo, ' + request.user.username + '! Du er autentisert.',
}
return Response(content)
I dette eksemplet spesifiserer `authentication_classes` at Token-autentisering skal brukes, og `permission_classes` spesifiserer at bare autentiserte brukere kan få tilgang til visningen.
- Inkluder Login API View:
Du trenger også et endepunkt for å opprette token ved vellykket innlogging:
from django.contrib.auth import authenticate
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
@api_view(['POST'])
@permission_classes([AllowAny])
def login(request):
username = request.data.get('username')
password = request.data.get('password')
user = authenticate(username=username, password=password)
if user:
token, _ = Token.objects.get_or_create(user=user)
return Response({'token': token.key})
else:
return Response({'error': 'Ugyldig legitimasjon'}, status=status.HTTP_401_UNAUTHORIZED)
Fordeler med Token-autentisering
- Enkelhet: Enkelt å implementere og forstå.
- Stateless: Hver token-forespørsel inneholder informasjon som lar den stå alene.
Ulemper med Token-autentisering
- Databasesavhengighet: Krever et databasesøk for hver forespørsel for å validere token. Dette kan påvirke ytelsen, spesielt i stor skala.
- Token-tilbakekalling: Å tilbakekalle en token krever å slette den fra databasen, noe som kan være komplisert.
- Skalerbarhet: Kanskje ikke den mest skalerbare løsningen for store API-er med høy trafikk på grunn av databasekostnadene.
JWT (JSON Web Token) Autentisering
JWT-autentisering er en mer moderne og sofistikert tilnærming. En JWT er et kompakt, URL-sikkert JSON-objekt som inneholder påstander om brukeren. Disse påstandene er digitalt signert ved hjelp av en hemmelig nøkkel eller et offentlig/privat nøkkelpar. Når en bruker logger inn, genererer serveren en JWT og sender den til klienten. Klienten inkluderer deretter denne JWT i 'Authorization'-headeren for påfølgende forespørsler. Serveren kan verifisere JWTs signatur uten å måtte få tilgang til en database, noe som gjør det til en mer effektiv og skalerbar løsning.
Implementering med DRF
DRF gir ikke innebygd støtte for JWT-autentisering, men flere utmerkede biblioteker gjør det enkelt å integrere. En av de mest populære er `djangorestframework-simplejwt`.
- Installer `djangorestframework-simplejwt`:
pip install djangorestframework-simplejwt
- Konfigurer DRF-innstillinger:
I `settings.py`-filen din legger du til følgende:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
'ALGORITHM': 'HS256',
'SIGNING_KEY': settings.SECRET_KEY,
'VERIFYING_KEY': None,
'AUTH_HEADER_TYPES': ('Bearer',),
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
}
Forklaring av innstillinger:
- `ACCESS_TOKEN_LIFETIME`: Hvor lenge access token er gyldig (eksempel, 5 minutter).
- `REFRESH_TOKEN_LIFETIME`: Hvor lenge refresh token er gyldig (eksempel, 1 dag). Refresh tokens brukes til å skaffe nye access tokens uten å kreve at brukeren logger på igjen.
- `ROTATE_REFRESH_TOKENS`: Om du vil rotere refresh tokens etter hver bruk.
- `BLACKLIST_AFTER_ROTATION`: Om du vil svarteliste gamle refresh tokens etter rotasjon.
- `ALGORITHM`: Algoritmen som brukes til å signere JWT (HS256 er et vanlig valg).
- `SIGNING_KEY`: Den hemmelige nøkkelen som brukes til å signere JWT (vanligvis Django SECRET_KEY).
- `AUTH_HEADER_TYPES`: Typen autorisasjonsoverskrift (vanligvis "Bearer").
- Inkluder Login og Refresh Token API Views:
`djangorestframework-simplejwt` gir visninger for å skaffe og oppdatere tokens. Inkluder dem i `urls.py`:
from django.urls import path
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
`TokenObtainPairView` gir access og refresh tokens etter vellykket autentisering. `TokenRefreshView` gir en ny access token når den leveres med en gyldig refresh token.
- Implementer API-visningene dine:
Her er et enkelt eksempel på en visning som krever JWT-autentisering:
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.authentication import JWTAuthentication
class ExampleView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
content = {
'message': 'Hallo, ' + request.user.username + '! Du er autentisert.',
}
return Response(content)
I likhet med Token-autentiseringseksemplet, spesifiserer `authentication_classes` at JWT-autentisering skal brukes, og `permission_classes` begrenser tilgangen til kun autentiserte brukere.
Fordeler med JWT-autentisering
- Skalerbarhet: Ingen databasesøk kreves for tokenvalidering, noe som gjør det mer skalerbart.
- Stateless: JWT inneholder all nødvendig informasjon for autentisering.
- Standardisert: JWT er en mye brukt standard, støttet av mange biblioteker og plattformer.
- Microservices-vennlig: Egnet for microservices-arkitekturer, da tjenester uavhengig kan verifisere JWT-er.
Ulemper med JWT-autentisering
- Kompleksitet: Mer komplekst å implementere enn Token-autentisering.
- Tokenstørrelse: JWT-er kan være større enn enkle tokens, noe som potensielt øker båndbreddebruken.
- Token-tilbakekalling: Å tilbakekalle en JWT er utfordrende. Når den er utstedt, er den gyldig til den utløper. Løsninger involverer svartelisting av tilbakekalte tokens, noe som gjeninnfører databasesavhengighet.
Token-tilbakekallingsstrategier
Både Token- og JWT-autentiseringsmetoder krever mekanismer for å tilbakekalle tilgang. Slik kan du nærme deg token-tilbakekalling:
Token-autentisering Tilbakekalling
Med Token-autentisering er tilbakekalling enkelt: bare slett token fra databasen:
from rest_framework.authtoken.models import Token
try:
token = Token.objects.get(user=request.user)
token.delete()
except Token.DoesNotExist:
pass
JWT-autentisering Tilbakekalling
JWT-tilbakekalling er mer komplekst fordi selve tokenet er selvstendig og ikke er avhengig av et databasesøk for validering (i utgangspunktet). Vanlige strategier inkluderer:
- Token svartelisting: Lagre tilbakekalte tokens i en svarteliste (f.eks. en databasetabell eller en Redis-cache). Før du validerer en JWT, må du sjekke om den er i svartelisten. `djangorestframework-simplejwt` gir innebygd støtte for svartelisting av refresh tokens.
- Korte utløpstider: Bruk korte utløpstider for access tokens og stol på refresh tokens for å skaffe nye access tokens ofte. Dette begrenser mulighetsvinduet for en kompromittert token som skal brukes.
- Roter refresh tokens: Roter refresh tokens etter hver bruk. Dette vil ugyldiggjøre gamle tokens hver gang og forhindre token-tyveri.
OAuth2 og OpenID Connect
For mer komplekse autentiserings- og autoriseringsscenarier, bør du vurdere å bruke OAuth2 og OpenID Connect. Disse standardene gir et robust rammeverk for å delegere tilgang til ressurser uten å dele legitimasjon. OAuth2 er primært en autorisasjonsprotokoll, mens OpenID Connect bygger på OAuth2 for å tilby autentiseringstjenester. Flere Django-pakker, som `django-oauth-toolkit` og `django-allauth`, letter integreringen av OAuth2 og OpenID Connect i DRF-API-ene dine.
Eksempelscenario: En bruker ønsker å gi en tredjepartsapplikasjon tilgang til dataene sine som er lagret i API-en din. Med OAuth2 kan brukeren autorisere applikasjonen uten å dele brukernavnet og passordet sitt. I stedet mottar applikasjonen en access token som den kan bruke til å få tilgang til brukerens data innenfor det definerte omfanget av tillatelser.
Velge riktig autentiseringsmetode
Den beste autentiseringsmetoden avhenger av dine spesifikke krav:
- Enkelhet og hastighet ved implementering: Token-autentisering er generelt enklere å implementere i utgangspunktet.
- Skalerbarhet: JWT-autentisering er mer skalerbar for API-er med høy trafikk.
- Sikkerhetskrav: Vurder følsomheten til dataene dine og sikkerhetsnivået som kreves. OAuth2/OpenID Connect tilbyr de mest robuste sikkerhetsfunksjonene, men krever mer kompleks implementering.
- Microservices-arkitektur: JWT-er er godt egnet for microservices, da hver tjeneste uavhengig kan verifisere tokens.
Beste praksis for API-autentisering
- Bruk HTTPS: Bruk alltid HTTPS for å kryptere kommunikasjonen mellom klienten og serveren, og beskytt legitimasjonen mot avlytting.
- Lagre hemmeligheter sikkert: Oppbevar aldri hemmelige nøkler eller passord i ren tekst. Bruk miljøvariabler eller sikre konfigurasjonsverktøy.
- Implementer hastighetsbegrensning: Beskytt API-en din mot misbruk ved å implementere hastighetsbegrensning for å begrense antall forespørsler en klient kan gjøre innen en gitt tidsperiode.
- Valider inndata: Valider alle inndata grundig for å forhindre injeksjonsangrep.
- Overvåk og logg: Overvåk API-en din for mistenkelig aktivitet og logg autentiseringshendelser for revisjonsformål.
- Oppdater biblioteker regelmessig: Hold Django-, DRF- og autentiseringsbibliotekene dine oppdatert for å dra nytte av sikkerhetsoppdateringer og forbedringer.
- Implementer CORS (Cross-Origin Resource Sharing): Konfigurer CORS riktig for å tillate bare pålitelige domener å få tilgang til API-en din fra nettlesere.
Konklusjon
Å velge riktig autentiseringsmetode er avgjørende for å sikre DRF-API-ene dine. Token-autentisering tilbyr enkelhet, mens JWT-autentisering gir skalerbarhet og fleksibilitet. Å forstå fordelene og ulempene ved hver metode, sammen med beste praksis for API-sikkerhet, vil gjøre deg i stand til å bygge robuste og sikre API-er som beskytter dataene og brukerne dine.
Husk å vurdere dine spesifikke behov og velg løsningen som best balanserer sikkerhet, ytelse og enkel implementering. Utforsk OAuth2 og OpenID Connect for mer komplekse autorisasjonsscenarier.